home *** CD-ROM | disk | FTP | other *** search
- /*
- * KISS+AX25 IP streams module for sunos 4.x
- *
- * Copyright 1991, 1992 by Theo de Raadt
- *
- * Theo de Raadt <deraadt@lego.cuc.ab.ca>
- * Thanks to William Graham <uug@indigo.cuc.ab.ca> for AX25 specs.
- *
- * Streams ideas ripped off from PPP and SLIP implimentations for
- * Sunos by Brad Clements and Rayan Zachariassen respectively.
- */
- #undef DEBUG
- #undef DEBUG2
- #define AX_NIT
-
- #include "ax.h"
- #if NAX > 0
-
- #include <sys/types.h>
- #include <sys/param.h>
- #include <sys/stream.h>
- #include <sys/stropts.h>
- #include <sys/dir.h>
- #include <sys/signal.h>
- #include <sys/user.h>
- #include <sys/mbuf.h>
- #include <sys/socket.h>
- #include <sys/sockio.h>
- #include <sys/syslog.h>
-
- #include <netinet/in.h>
-
- #include <net/if.h>
- #include <net/nit_if.h>
- #include <netinet/if_ether.h>
- #include <sys/if_ax.h>
-
- #include <net/netisr.h>
-
- #include <netinet/in_systm.h>
- #include <netinet/in_var.h>
- #include <netinet/ip.h>
-
- #ifdef AX_NIT
- static struct ether_header nitheader = { {{1}}, {{2}}, ETHERTYPE_IP };
- static struct nit_if nif = {(caddr_t)&nitheader, sizeof(nitheader), 0, 0};
-
- static struct ether_header nitheader_arp = { {{1}}, {{2}}, ETHERTYPE_ARP };
- static struct nit_if nif_arp = {(caddr_t)&nitheader_arp, sizeof(nitheader_arp), 0, 0};
- #endif
-
- int ax_attach();
- static int ax_open(), ax_close(), ax_rput(), ax_wput(), ax_wsrv();
- static int ax_ioctl(), ax_output();
- static struct mbuf *ax_btom();
-
- static struct module_info minfo = {
- 0xabce, AXSTREAMNAME, 0, INFPSZ, 16384, 4096
- };
-
- static struct qinit r_init = {
- ax_rput, NULL, ax_open, ax_close, NULL, &minfo, NULL
- };
-
- static struct qinit w_init = {
- ax_wput, ax_wsrv, ax_open, ax_close, NULL, &minfo, NULL
- };
-
- struct streamtab axinfo = {
- &r_init, &w_init, NULL, NULL, NULL
- };
-
- static struct axpriv {
- struct arpcom arpcom;
- queue_t *q;
- u_char *buf;
- u_char *dp;
- u_int inlen;
- u_char gotesc, toobig;
- } axpriv[NAX];
-
- static u_char ax25broadcastaddr[7] = {
- 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1
- };
- static struct ether_addr ethernulladdr;
-
- int
- ax_attach(unit)
- int unit;
- {
- register struct ifnet *ifp = &axpriv[unit].arpcom.ac_if;
-
- ifp->if_name = AXIFNAME;
- ifp->if_mtu = AX25MTU;
- ifp->if_flags = IFF_BROADCAST;
- ifp->if_unit = unit;
- ifp->if_ioctl = ax_ioctl;
- ifp->if_output = ax_output;
- ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
- if_attach(ifp);
- return 0;
- }
-
- static int
- ax_open(q, dev, flag, sflag)
- queue_t *q;
- dev_t dev;
- int flag, sflag;
- {
- struct axpriv *axp;
- int unit, s;
-
- if( !suser()) {
- u.u_error = EPERM;
- return OPENFAIL;
- }
-
- s = splstr();
- for( unit=0; unit<NAX; ++unit) {
- axp = &axpriv[unit];
-
- if(axp->buf)
- continue;
- if(axp->arpcom.ac_if.if_mtu == 0)
- ax_attach(unit);
- axp->arpcom.ac_if.if_flags |= IFF_RUNNING;
- axp->buf = (u_char *)kmem_alloc(AX25MTU);
- axp->dp = axp->buf + sizeof(struct ifnet *);
- axp->inlen = 0;
- axp->q = WR(q);
- WR(q)->q_ptr = q->q_ptr = (caddr_t)axp;
- (void) splx(s);
- log(LOG_INFO, "ax%d: coming up\n", unit);
- return unit;
- }
- splx(s);
- log(LOG_INFO, "ax%d: no more devices available\n", NAX);
- return OPENFAIL;
- }
-
- static int
- ax_close(q, flag)
- queue_t *q;
- int flag;
- {
- struct axpriv *axp;
- int s;
-
- s = splimp();
- axp = (struct axpriv *)q->q_ptr;
- if(axp) {
- log(LOG_INFO, "ax%d: going down\n", axp->arpcom.ac_if.if_unit);
- if_down(&axp->arpcom.ac_if);
- axp->arpcom.ac_if.if_flags &= ~(IFF_UP|IFF_RUNNING);
- if(axp->buf)
- kmem_free(axp->buf, AX25MTU);
- axp->buf = NULL;
- axp->q = NULL;
- }
- (void) splx(s);
- }
-
- static int
- ax_wput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- struct axpriv *axp;
- char ax25[7];
- struct iocblk *iocp;
-
- switch(mp->b_datap->db_type) {
- case M_FLUSH:
- if(*mp->b_rptr & FLUSHW)
- flushq(q, FLUSHDATA);
- putnext(q, mp);
- break;
- case M_DATA:
- putq(q, mp);
- break;
- case M_IOCTL:
- iocp = (struct iocblk *)mp->b_rptr;
- axp = (struct axpriv *)q->q_ptr;
- switch(iocp->ioc_cmd) {
- case AXIOSHADDR:
- bcopy((caddr_t)mp->b_cont->b_rptr,
- (caddr_t)&axp->arpcom.ac_enaddr,
- sizeof(struct ether_addr));
- mp->b_datap->db_type = M_IOCACK;
- iocp->ioc_rval = iocp->ioc_count = iocp->ioc_error = 0;
- qreply(q, mp);
- log(LOG_INFO, "ax%d: ether %2x:%2x:%2x:%2x:%2x:%2x ax25 ",
- axp->arpcom.ac_if.if_unit,
- axp->arpcom.ac_enaddr.ether_addr_octet[0],
- axp->arpcom.ac_enaddr.ether_addr_octet[1],
- axp->arpcom.ac_enaddr.ether_addr_octet[2],
- axp->arpcom.ac_enaddr.ether_addr_octet[3],
- axp->arpcom.ac_enaddr.ether_addr_octet[4],
- axp->arpcom.ac_enaddr.ether_addr_octet[5]);
- ax_ether2ax(&axp->arpcom.ac_enaddr, ax25);
- print_ax25addr(ax25);
- printf("\n");
- return;
- case AXIOGUNIT:
- iocp->ioc_rval = 0;
- if( mp->b_cont = allocb(sizeof(int), BPRI_MED) ) {
- u_char *cp = mp->b_cont->b_wptr;
-
- mp->b_datap->db_type = M_IOCACK;
- *((int *)cp) = axp->arpcom.ac_if.if_unit;
- mp->b_cont->b_wptr += sizeof(int);
- iocp->ioc_count = sizeof(int);
- iocp->ioc_error = 0;
- qreply(q, mp);
- break;
- }
- iocp->ioc_error = ENOSR;
- mp->b_datap->db_type = M_IOCNAK;
- qreply(q, mp);
- return;
- default:
- log(LOG_INFO, "ax%d: unknown ioc %8x\n",
- axp->arpcom.ac_if.if_unit, iocp->ioc_cmd);
- putnext(q, mp);
- return;
- }
- break;
- default:
- putnext(q, mp);
- }
- }
-
- static int
- ax_rput(q, mp)
- queue_t *q;
- mblk_t *mp;
- {
- struct axpriv *axp = (struct axpriv *)q->q_ptr;
- struct ifnet *ifp;
- register u_char c, *rp;
- register mblk_t *bp;
- struct mbuf *m;
- int proto, forus, s;
-
- if( axp==NULL ) {
- log(LOG_INFO, "ax_rput: axp is NULL\n");
- freemsg(mp);
- return;
- }
- if( axp->buf==NULL ) {
- log(LOG_INFO, "ax_rput: axp->buf is NULL\n");
- freemsg(mp);
- return;
- }
-
- ifp = &axp->arpcom.ac_if;
- switch(mp->b_datap->db_type) {
- case M_DATA:
- break;
- case M_FLUSH:
- if(*mp->b_rptr & FLUSHR)
- flushq(q, FLUSHDATA);
- putnext(q, mp);
- return;
- case M_UNHANGUP:
- log(LOG_INFO, "ax%d: M_UNHANGUP\n", ifp->if_unit);
- axp->q = WR(q); /* hook us up again */
- putnext(q, mp);
- putctl1(q->q_next, M_PCSIG, SIGURG);
- return;
- case M_HANGUP:
- log(LOG_INFO, "ax%d: M_HANGUP\n", ifp->if_unit);
- s = splstr();
- axp->q = NULL; /* cause ax_output to return ENETDOWN */
- (void) splx(s);
- putnext(q, mp);
- return;
- case M_BREAK:
- case M_IOCACK:
- putnext(q, mp);
- return;
- default:
- log(LOG_INFO, "ax%d: rput streams message type %d discarded\n",
- ifp->if_unit, mp->b_datap->db_type);
- putnext(q, mp);
- return;
- }
-
- /*
- * Perform the KISS protocol on the streams message, and add the bytes
- * to a packet reconstruction buffer. When a complete AX25 packet has
- * been collected, strip the AX25 layer and provide the IP (or ARP) packet
- * inside to the networking code.
- */
- for( bp=mp; bp; bp=bp->b_cont) {
- rp = bp->b_rptr;
- while( rp < bp->b_wptr) {
- c = *rp++;
- /*printf("K %2x\n", c);*/
- if(axp->gotesc) {
- axp->gotesc = 0;
- if(c==KISS_TEND)
- c = KISS_END;
- else if(c==KISS_TESC)
- c = KISS_ESC;
- #ifdef DEBUG
- else
- log(LOG_INFO, "ax%d: kiss ESC error (c=%d)\n",
- ifp->if_unit, c);
- #endif
- } else if(c==KISS_END) {
- if(axp->toobig) {
- axp->toobig = 0;
- /*printf("ax%d: packet toobig\n",
- ifp->if_unit);*/
- axp->inlen = 0;
- continue;
- }
- if(axp->inlen==0)
- continue;
-
- /*
- * buf contains KISS_DATA followed by an AX25
- * packet. Extract the IP packet lurking inside
- * AX25 packet..
- */
- m = ax_btom(axp, &proto, &forus);
- axp->dp = axp->buf + sizeof(struct ifnet *);
- ifp->if_ipackets++;
- axp->inlen = 0;
- if(!m) {
- ifp->if_ierrors++;
- continue;
- }
-
- switch(proto) {
- case AX25PID_IP:
- #ifdef AX_NIT
- if(ifp->if_flags & IFF_PROMISC) {
- struct mbuf *nm = m;
- int len = 0;
-
- do {
- len += nm->m_len;
- } while( nm=nm->m_next );
- len -= sizeof(struct ifnet *);
- m->m_off += sizeof(struct ifnet *);
- nif.nif_bodylen = len;
- snit_intr(&axp->arpcom, m, &nif);
- m->m_off -= sizeof(struct ifnet *);
- }
- #endif
- if(!forus) {
- m_freem(m);
- break;
- }
- s = splimp();
- if( IF_QFULL(&ipintrq) ) {
- IF_DROP(&ipintrq);
- ifp->if_ierrors++;
- m_freem(m);
- (void) splx(s);
- } else {
- IF_ENQUEUE(&ipintrq, m);
- schednetisr(NETISR_IP);
- (void) splx(s);
- #ifdef DEBUG
- log(LOG_INFO, "handing off to IP\n");
- #endif
- }
- break;
- case AX25PID_ARP:
- #ifdef AX_NIT
- if(ifp->if_flags & IFF_PROMISC) {
- struct mbuf *nm = m;
- int len = 0;
-
- do {
- len += nm->m_len;
- } while( nm=nm->m_next );
- len -= sizeof(struct ifnet *);
- m->m_off += sizeof(struct ifnet *);
- nif_arp.nif_bodylen = len;
- snit_intr(&axp->arpcom, m, &nif_arp);
- m->m_off -= sizeof(struct ifnet *);
- }
- #endif
- if(!forus) {
- m_freem(m);
- break;
- }
- #ifdef DEBUG
- printf("[INCOMING ethernet arp packet]");
- ax25_arpdebug(m);
- #endif
- arpinput(&axp->arpcom, m);
- break;
- default:
- #ifdef DEBUG2
- printf("ax%d: unknown protocol %d\n",
- ifp->if_unit,
- proto);
- #endif
- m_freem(m);
- break;
- }
- continue;
- } else if(c==KISS_ESC) {
- axp->gotesc = 1;
- continue;
- }
- if(++axp->inlen > AX25MTU) {
- if(axp->toobig)
- continue;
- axp->toobig = 1;
- ifp->if_ierrors++;
- axp->dp = axp->buf + sizeof(struct ifnet *);
- continue;
- } else
- *axp->dp++ = c;
- }
- bp->b_rptr = rp;
- }
- freemsg(mp);
- return;
- }
-
-
- static struct mbuf *
- ax_btom(axp, protop, forusp)
- struct axpriv *axp;
- int *protop, *forusp;
- {
- struct ax25_hdr *ax;
- struct mbuf *m, **mp, *top = NULL;
- struct ifnet *ifp;
- struct ether_addr oureth;
- int len, count;
- caddr_t cp;
-
- ax = (struct ax25_hdr *)(axp->buf + sizeof(struct ifnet *) + 1);
-
- /*
- * digipeaters are not supported (they could be supported - could
- * correct the AX25 packet's fields, KISS encode it, and send a
- * message downstream to the TNC.)
- *
- * The IP packet must come in an AX25 UI frame.
- */
- if(ax->ah_cmd != AX25CMD_UI) {
- #ifdef DEBUG2
- printf("ax%d: ax25 frame not UI, cmd=%2x\n",
- axp->arpcom.ac_if.if_unit, ax->ah_cmd);
- #endif
- return NULL;
- }
-
- #ifdef DEBUG2
- printf("ax%d: ", axp->arpcom.ac_if.if_unit);
- print_ax25addr(ax->ah_src);
- printf("->");
- print_ax25addr(ax->ah_dst);
- printf(" [%d]\n", axp->inlen - sizeof(struct ax25_hdr) - 1);
- #endif
-
- /*
- * is this packet to us?
- */
- *forusp = 1;
- ax_ax2ether(ax->ah_dst, &oureth);
- if( bcmp((caddr_t)&oureth, (caddr_t)&axp->arpcom.ac_enaddr,
- sizeof oureth) &&
- bcmp((caddr_t)ax25broadcastaddr, (caddr_t)&axp->arpcom.ac_enaddr,
- sizeof oureth)) {
- *forusp = 0;
- }
-
- /*
- * packet not for us, and not promisc mode --> can out.
- */
- if( !(axp->arpcom.ac_if.if_flags & IFF_PROMISC) && *forusp==0)
- return NULL;
-
- /*
- * check acceptable protocols
- */
- switch(ax->ah_pid) {
- case AX25PID_IP:
- case AX25PID_ARP:
- break;
- default:
- #ifdef DEBUG2
- printf("ax%d: packet discarded - protocol %d\n",
- axp->arpcom.ac_if.if_unit, ax->ah_pid);
- #endif
- return NULL;
- }
-
- *protop = (int)(ax->ah_pid);
- ifp = &axp->arpcom.ac_if;
- cp = (caddr_t)(axp->buf + sizeof(struct ifnet *) + 1 + sizeof(struct ax25_hdr));
- mp = ⊤
- len = axp->inlen - 1 - sizeof(struct ax25_hdr);
- while(len>0) {
- MGET(m, M_DONTWAIT, MT_DATA);
- if(m == NULL) {
- if(top)
- m_freem(top);
- return NULL;
- }
- *mp = m;
- if(ifp) {
- m->m_off += sizeof(ifp);
- count = MIN(len, MLEN - sizeof(ifp));
- bcopy(cp, mtod(m, caddr_t), count);
- m->m_len = count;
- m->m_off -= sizeof(ifp);
- m->m_len += sizeof(ifp);
- *mtod(m, struct ifnet **) = ifp;
- ifp = NULL;
- } else {
- count = MIN(len, MLEN);
- bcopy(cp, mtod(m, caddr_t), count);
- m->m_len = count;
- }
- cp += count;
- len -= count;
- mp = &m->m_next;
- }
- if(ax->ah_pid== AX25PID_ARP) {
- top->m_off += sizeof(ifp); /* XXX ax_ax2etherarp() weak */
- ax_ax2etherarp(top);
- top->m_off -= sizeof(ifp);
- }
-
- return top;
- }
-
-
- static int
- ax_wsrv(q)
- queue_t *q;
- {
- register mblk_t *mp;
-
- while( mp=getq(q) ) {
- if( !canput(q->q_next)) {
- putbq(q, mp);
- return;
- }
- putnext(q, mp);
- }
- }
-
- /* %%% ifconfig ether #:#:#:#:#:# not working */
- static int
- ax_ioctl(ifp, cmd, data)
- struct ifnet *ifp;
- int cmd;
- caddr_t data;
- {
- register struct ifaddr *ifa = (struct ifaddr *)data;
- register struct ifreq *ifr = (struct ifreq *)data;
- int error = 0, s;
-
- if(ifa==NULL)
- return EFAULT;
- s = splimp();
- switch(cmd) {
- case SIOCSIFFLAGS:
- if(!data) /* IFF_PROMISC change */
- break;
- if(!suser()) {
- error = EPERM;
- break;
- }
- ifp->if_flags &= IFF_CANTCHANGE;
- ifp->if_flags |= (ifr->ifr_flags & ~IFF_CANTCHANGE);
- break;
- case SIOCGIFFLAGS:
- ifr->ifr_flags = ifp->if_flags;
- break;
- case SIOCSIFADDR:
- switch(ifa->ifa_addr.sa_family) {
- case AF_INET:
- ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr;
- ifp->if_flags |= IFF_UP;
- break;
- default:
- error = EAFNOSUPPORT;
- break;
- }
- break;
- case SIOCSIFBRDADDR:
- if(ifa->ifa_addr.sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
- case SIOCSIFNETMASK:
- if(ifa->ifa_addr.sa_family != AF_INET)
- error = EAFNOSUPPORT;
- break;
- default:
- error = EINVAL;
- }
- (void) splx(s);
- return error;
- }
-
- static int
- ax_output(ifp, m0, dst)
- struct ifnet *ifp;
- struct mbuf *m0;
- struct sockaddr *dst;
- {
- struct axpriv *axp;
- struct ax25_hdr ax25;
- struct ether_header *eth;
- struct mbuf *m = m0;
- int i, len, s, n;
- struct in_addr idst;
- u_char *cp, *cp2;
- mblk_t *mp;
-
- axp = &axpriv[ifp->if_unit];
- if(axp->q == NULL)
- return ENETDOWN;
-
- /* printf("ax%d: trying to send packet\n", ifp->if_unit); */
-
- switch(dst->sa_family) {
- case AF_INET:
- #ifdef AX_NIT
- if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) {
- struct mbuf *nm = m0;
- int len = 0;
-
- do {
- len += nm->m_len;
- } while( nm=nm->m_next );
- nif.nif_bodylen = len;
- snit_intr(&axp->arpcom, m0, &nif);
- }
-
- #endif
- idst = ((struct sockaddr_in *)dst)->sin_addr;
- ((struct arpcom *)ifp)->ac_lastip = idst;
- m = m0;
- if( !arpresolve((struct arpcom *)ifp, m)) {
- return 0;
- }
- #ifdef DEBUG2
- len = 0;
- for(m=m0; m; m=m->m_next) {
- cp = mtod(m, u_char *);
- n = m->m_len;
- while(n-->0) {
- if( !(len++ % 16) )
- printf("\n\t");
- printf("%2x ", *cp++);
- }
- }
- if( len % 16 )
- printf("\n");
- #endif
- ax25.ah_pid = AX25PID_IP;
- ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src);
- ax_ether2ax(&((struct arpcom *)ifp)->ac_lastarp, ax25.ah_dst);
- #ifdef DEBUG2
- printf("ax%d: sending to ", ifp->if_unit);
- print_ax25addr(ax25.ah_dst);
- printf("\n");
- #endif
- break;
- case AF_UNSPEC:
- eth = (struct ether_header *)dst->sa_data;
- switch(eth->ether_type) {
- case ETHERTYPE_ARP:
- case ETHERTYPE_REVARP:
- #ifdef AX_NIT
- if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) {
- struct mbuf *nm = m0;
- int len = 0;
-
- do {
- len += nm->m_len;
- } while( nm=nm->m_next );
- nif_arp.nif_bodylen = len;
- snit_intr(&axp->arpcom, m0, &nif_arp);
- }
-
- #endif
- #ifdef DEBUG2
- printf("AF_UNSPEC: ARP\n");
- printf("[ethernet arp packet]");
- len = 0;
- for(m=m0; m; m=m->m_next) {
- cp = mtod(m, u_char *);
- n = m->m_len;
- while(n-->0) {
- if( !(len++ % 16) )
- printf("\n\t");
- printf("%2x ", *cp++);
- }
- }
- if( len % 16 )
- printf("\n");
- #endif
-
- ax_ether2axarp(m0);
- ax25.ah_pid = AX25PID_ARP;
- ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src);
- ax_ether2ax(ð->ether_dhost, ax25.ah_dst);
- #ifdef DEBUG2
- printf("[AX25 arp packet]");
- #endif
- break;
- default:
- printf("AF_UNSPEC: unknown ether_type %4x",
- ntohs(eth->ether_type));
- ax25.ah_pid = AX25PID_IP; /* wrong */
- ax_ether2ax(ð->ether_shost, ax25.ah_src);
- ax_ether2ax(ð->ether_dhost, ax25.ah_dst);
- break;
- }
-
- #ifdef DEBUG2
- len = 0;
- for(m=m0; m; m=m->m_next) {
- cp = mtod(m, u_char *);
- n = m->m_len;
- while(n-->0) {
- if( !(len++ % 16) )
- printf("\n\t");
- printf("%2x ", *cp++);
- }
- }
- if( len % 16 )
- printf("\n");
- #endif
-
- break;
- default:
- log(LOG_INFO, "ax%d: cannot handle af%d\n", ifp->if_unit,
- dst->sa_family);
- m_freem(m0);
- return EAFNOSUPPORT;
- }
-
- ax25.ah_cmd = AX25CMD_UI;
- ax25.ah_src[6] |= 0x01; /* %%% set low bit on src */
-
- /*
- * run through the ax25_hdr and the packet buffer counting
- * how much space we need for KISS encoding.
- */
- len = 2; /* KISS_END, KISS_DATA */
- for(i=0, cp=(u_char *)&ax25; i< sizeof(ax25); i++, cp++) {
- len++;
- if(*cp==KISS_END || *cp==KISS_ESC)
- len++;
- }
- for(m=m0; m; m=m->m_next) {
- cp = mtod(m, u_char *);
- for(i=0; i< m->m_len; i++, cp++) {
- len++;
- if(*cp==KISS_END || *cp==KISS_ESC)
- len++;
- }
- }
- len++; /* KISS_END */
-
- if( !(mp = allocb(len, BPRI_MED)) ) {
- log(LOG_INFO, "ax%d: ax_output cannot allocb %d bytes\n",
- ifp->if_unit, len);
- m_freem(m0);
- return ENOSR;
- }
-
- #ifdef DEBUG2
- cp2 = mp->b_wptr;
- #endif
-
- /*
- * KISS-format the ax25 header and data into mp.
- */
- *mp->b_wptr++ = KISS_END;
- *mp->b_wptr++ = KISS_DATA;
- for(i=0, cp=(u_char *)&ax25; i<sizeof(ax25); i++, cp++) {
- switch(*cp) {
- case KISS_END:
- *mp->b_wptr++ = KISS_ESC;
- *mp->b_wptr++ = KISS_TEND;
- break;
- case KISS_ESC:
- *mp->b_wptr++ = KISS_ESC;
- *mp->b_wptr++ = KISS_TESC;
- break;
- default:
- *mp->b_wptr++ = *cp;
- break;
- }
- }
- for(m=m0; m; m=m->m_next) {
- cp = mtod(m, u_char *);
- for(i=0; i< m->m_len; i++, cp++) {
- switch(*cp) {
- case KISS_END:
- *mp->b_wptr++ = KISS_ESC;
- *mp->b_wptr++ = KISS_TEND;
- break;
- case KISS_ESC:
- *mp->b_wptr++ = KISS_ESC;
- *mp->b_wptr++ = KISS_TESC;
- break;
- default:
- *mp->b_wptr++ = *cp;
- break;
- }
- }
- }
- *mp->b_wptr++ = KISS_END; /* superfluous, really */
-
- #ifdef DEBUG2
- printf("actual serial output:\n");
- while(cp2 < mp->b_wptr)
- printf("%2x ", *cp2++);
- printf("\n");
- #endif
-
- s = splstr();
- if(axp->q)
- putq(axp->q, mp);
- else
- freemsg(mp);
- (void) splx(s);
- m_freem(m0);
- return 0;
- }
-
- /*
- * convert an ethernet ARP packet to an AX25 ARP packet. The AX25 frame
- * header is not included.
- */
- ax_ether2axarp(m)
- struct mbuf *m;
- {
- struct arphdr *arp = mtod(m, struct arphdr *);
- struct ether_addr eth1, eth2;
- struct in_addr in1, in2;
- caddr_t cp;
-
- arp->ar_hrd = AX25_HARDTYPE;
- arp->ar_pro = AX25_IPTYPE;
- arp->ar_hln = 7;
-
- cp = ((caddr_t)arp) + sizeof(struct arphdr);
- bcopy(cp, (caddr_t)ð1, sizeof(struct ether_addr));
- cp += sizeof(struct ether_addr);
- bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr));
- cp += sizeof(struct in_addr);
- bcopy(cp, (caddr_t)ð2, sizeof(struct ether_addr));
- cp += sizeof(struct ether_addr);
- bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr));
-
- cp = ((caddr_t)arp) + sizeof(struct arphdr);
- ax_ether2ax(ð1, (u_char *)cp);
- cp += 7;
- bcopy((caddr_t)&in1, cp, sizeof(struct in_addr));
- cp += sizeof(struct in_addr);
- ax_ether2ax(ð2, (u_char *)cp);
- cp += 7;
- bcopy((caddr_t)&in2, cp, sizeof(struct in_addr));
-
- m->m_len += 2;
- return 0;
- }
-
- /*
- * convert an AX25 ARP packet to an ethernet ARP packet. The AX25 frame
- * is assumed to have been already stripped off.
- */
- ax_ax2etherarp(m)
- struct mbuf *m;
- {
- struct arphdr *arp = mtod(m, struct arphdr *);
- u_char axa1[7], axa2[7];
- struct in_addr in1, in2;
- caddr_t cp;
-
- #ifdef DEBUG2
- printf("[INCOMING AX25 arp packet]");
- ax25_arpdebug(m);
- #endif
-
- arp->ar_hrd = ARPHRD_ETHER;
- arp->ar_pro = ETHERTYPE_IP;
- arp->ar_hln = sizeof(struct ether_addr);
-
- cp = ((caddr_t)arp) + sizeof(struct arphdr);
- bcopy(cp, (caddr_t)axa1, 7);
- cp += 7;
- bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr));
- cp += sizeof(struct in_addr);
- bcopy(cp, (caddr_t)axa2, 7);
- cp += 7;
- bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr));
-
- cp = ((caddr_t)arp) + sizeof(struct arphdr);
- ax_ax2ether(axa1, (struct ether_addr *)cp);
- cp += sizeof(struct ether_addr);
- bcopy((caddr_t)&in1, cp, sizeof(struct in_addr));
- cp += sizeof(struct in_addr);
- ax_ax2ether(axa2, (struct ether_addr *)cp);
- cp += sizeof(struct ether_addr);
- bcopy((caddr_t)&in2, cp, sizeof(struct in_addr));
-
- m->m_len -= 2;
- return 0;
- }
-
- /*
- * convert an ax25_addr to an ether_addr
- */
- ax_ax2ether(axhp, ethp)
- u_char *axhp;
- struct ether_addr *ethp;
- {
- u_char c;
- int i;
-
- #ifdef DEBUG2
- for(i=0; i<6; i++)
- printf("%2x.", axhp[i]);
- printf("%2x '", axhp[6]);
-
- for(i=0; i<(7-1); i++)
- printf("%c", (axhp[i]>>1) & 0x7f );
- printf("-%c' == ", (axhp[6]&0x7f)>>1 & 0x7f );
- #endif
-
- if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr,
- sizeof(ax25broadcastaddr)) ) {
- bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp,
- sizeof(struct ether_addr));
- goto done;
- }
-
- ethp->ether_addr_octet[0] = 0x99;
- c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc);
- c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03);
- ethp->ether_addr_octet[1] = c;
- c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0);
- c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f);
- ethp->ether_addr_octet[2] = c;
- c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0);
- c |= ((((axhp[3]>>1) - ' ') ) & 0x3f);
- ethp->ether_addr_octet[3] = c;
- c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc);
- c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03);
- ethp->ether_addr_octet[4] = c;
- c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0);
- c |= (((((axhp[6]&0x7f)>>1) - '0') ) & 0x0f);
- ethp->ether_addr_octet[5] = c;
-
- done:
- #ifdef DEBUG2
- for(i=0; i<sizeof(struct ether_addr)-1; i++)
- printf("%2x:", ethp->ether_addr_octet[i]);
- printf("%2x\n", ethp->ether_addr_octet[5]);
- #endif
- return 0;
- }
-
- /*
- * convert an ether_addr to an ax25_addr
- */
- ax_ether2ax(ethp, axhp)
- struct ether_addr *ethp;
- u_char *axhp;
- {
- u_char c;
- int i;
-
- #ifdef DEBUG2
- for(i=0; i<sizeof(struct ether_addr)-1; i++)
- printf("%2x:", ethp->ether_addr_octet[i]);
- printf("%2x == ", ethp->ether_addr_octet[5]);
- #endif
-
- if( !bcmp((caddr_t)ethp, (caddr_t)ðernulladdr,
- sizeof(struct ether_addr))) {
- #ifdef DEBUG2
- printf("nothing\n");
- #endif
- for(i=0; i<7; i++)
- axhp[i] = (u_char)0;
- return;
- }
- if( !bcmp((caddr_t)ethp, (caddr_t)ðerbroadcastaddr,
- sizeof(struct ether_addr))) {
- bcopy((caddr_t)ax25broadcastaddr, (caddr_t)axhp,
- sizeof(ax25broadcastaddr));
- goto done;
- }
- c = ethp->ether_addr_octet[0];
- if(c != 0x99) {
- #ifdef DEBUG2
- printf("[NO MAPPING]\n");
- #endif
- for(i=0; i<7; i++)
- axhp[i] = (u_char)0;
- return;
- }
- c = (ethp->ether_addr_octet[1] >> 2) & 0x3f;
- axhp[0] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[1] << 4) & 0x30;
- c |= (ethp->ether_addr_octet[2] >> 4) & 0x0f;
- axhp[1] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[2] << 2) & 0x3c;
- c |= (ethp->ether_addr_octet[3] >> 6) & 0x03;
- axhp[2] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[3] ) & 0x3f;
- axhp[3] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[4] >> 2) & 0x3f;
- axhp[4] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[4] << 4) & 0x30;
- c |= (ethp->ether_addr_octet[5] >> 4) & 0x0f;
- axhp[5] = (u_char)((c + ' ') << 1);
- c = (ethp->ether_addr_octet[5] ) & 0x0f;
- axhp[6] = (u_char)((c + '0') << 1);
-
- done:
- #ifdef DEBUG2
- for(i=0; i<6; i++)
- printf("%2x.", axhp[i]);
- printf("%2x '", axhp[6]);
-
- for(i=0; i<6; i++)
- printf("%c", (axhp[i] >> 1) & 0x7f );
- printf("-%c'\n", ((axhp[6] & 0x7f) >> 1) & 0x7f );
- #endif
- return;
- }
-
- print_ax25addr(axhp)
- u_char *axhp;
- {
- int i;
-
- #ifdef DEBUG2
- for(i=0; i<6; i++)
- printf("%2x.", axhp[i]);
- printf("%2x", axhp[6]);
- #endif
-
- printf("(");
- for(i=0; i<6; i++)
- printf("%c", (axhp[i]>>1) & 0x7f );
- printf("-%c)", ((axhp[6]&0x7f)>>1) & 0x7f );
- }
-
- ax25_arpdebug(m0)
- struct mbuf *m0;
- {
- struct mbuf *m;
- int len, n;
- u_char *cp;
-
- len = 0;
- for(m=m0; m; m=m->m_next) {
- printf("*");
- cp = mtod(m, u_char *);
- n = m->m_len;
- while(n-->0) {
- if( !(len++ % 16) )
- printf("\n\t");
- printf("%2x ", *cp++);
- }
- }
- if( len % 16 )
- printf("\n");
- }
-
-
- #endif /* !(NAX > 0) */
-
-